package org.voidness.oje2d;

import java.awt.Dimension;
import java.awt.Toolkit;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.URL;
import java.util.Calendar;

import javax.swing.ImageIcon;

import org.lwjgl.Sys;

/** Common utilities for the engine. */
public class Utils {
    /** The default proximity radius for the players */
    public static final int PROXIMITY_RADIUS = 10;

    /** Number of ticks in a second */
    private static long timerTicksPerSecond = Sys.getTimerResolution();

    /** Dump method information type */
    public static final int INFORMATION = 0;

    /** Dump method error type */
    public static final int ERROR = 1;

    /** Dump method warning type */
    public static final int WARNING = 2;

    /** Window alignment X center and Y center */
    public static final int CENTER_CENTER = 0;

    /** Window alignment X left and Y center */
    public static final int LEFT_CENTER = 1;

    /** JPEG image extension */
    public final static String jpeg = "jpeg";

    /** JPG image extension */
    public final static String jpg = "jpg";

    /** GIF image extension */
    public final static String gif = "gif";

    /** TIFF image extension */
    public final static String tiff = "tiff";

    /** TIF image extension */
    public final static String tif = "tif";

    /** PNG image extension */
    public final static String png = "png";

    /** BMP image extension */
    public final static String bmp = "bmp";

    /**
     * Gets the extension of a file.
     * 
     * @param mFile The file to extract the extension from
     * @return The extension
     */
    public static String getExtension(File mFile) {
        String extension = null;
        String name = mFile.getName();
        int i = name.lastIndexOf('.');

        if (i > 0 && i < name.length() - 1) {
            extension = name.substring(i + 1).toLowerCase();
        }
        return extension;
    }

    /**
     * Returns an ImageIcon, or null if the path was invalid.
     * 
     * @param mPath The path for the icon
     * @return An image icon
     */
    public static ImageIcon createImageIcon(String mPath) {
        URL imgURL = Utils.class.getResource(mPath);
        if (imgURL != null) {
            return new ImageIcon(imgURL);
        } else {
            // System.err.println("Couldn't find file: " + path);
            return null;
        }
    }

    /**
     * Dump a message to System.out
     * 
     * @param mMessage The text to write
     * @param mType The message type
     */
    public static void dump(String mMessage, int mType) {
        switch (mType) {
        case INFORMATION:
            System.out.println("(" + getSystemTime() + ") [INF] " + mMessage);
            break;

        case ERROR:
            System.out.println("(" + getSystemTime() + ") [ERR] " + mMessage);
            break;

        case WARNING:
            System.out.println("(" + getSystemTime() + ") [WAR] " + mMessage);
            break;
        }
    }

    /**
     * Get the current date.
     * 
     * @return A string with the current system date (DD-MM-YYYY)
     */
    public static String getSystemDate() {
        String dateString = new String();

        Calendar date = Calendar.getInstance();

        int day = date.get(Calendar.DAY_OF_MONTH);
        int month = date.get(Calendar.MONTH + 1);
        int year = date.get(Calendar.YEAR);

        if (day < 10) {
            dateString += "0";
        }
        dateString += day + "-";

        if (month < 10) {
            dateString += "0";
        }
        dateString += month + "-";

        dateString += year;

        return dateString;
    }

    /**
     * Get the current time.
     * 
     * @return A string with the current system time (HH:MM:SS)
     */
    public static String getSystemTime() {
        String timeString = new String();

        Calendar date = Calendar.getInstance();

        int hours = date.get(Calendar.HOUR_OF_DAY);
        int minutes = date.get(Calendar.MINUTE);
        int seconds = date.get(Calendar.SECOND);

        if (hours < 10) {
            timeString += "0";
        }
        timeString += hours + ":";

        if (minutes < 10) {
            timeString += "0";
        }
        timeString += minutes + ":";

        if (seconds < 10) {
            timeString += "0";
        }
        timeString += seconds;

        return timeString;
    }

    /**
     * A method to align a window.
     * 
     * @param mWindow The window to align
     * @param mAlign The type of alignment
     */
    public static void alignWindow(java.awt.Window mWindow, int mAlign) {
        // Get the size of the screen
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        int w = mWindow.getSize().width;
        int h = mWindow.getSize().height;
        int x = 0, y = 0;

        // Determine the new location of the window
        switch (mAlign) {
        default:
        case CENTER_CENTER: {
            x = (dim.width - w) / 2;
            y = (dim.height - h) / 2;
        }
            break;

        case LEFT_CENTER: {
            x = 0;
            y = (dim.height - h) / 2;
        }
            break;
        }

        // Move the window
        mWindow.setLocation(x, y);
    }

    /**
     * Get the current ticks in milliseconds.
     * 
     * @return The current time
     */
    public static long getTime() {
        // we get the "timer ticks" from the high resolution timer
        // multiply by 1000 so our end result is in milliseconds
        // then divide by the number of ticks in a second giving
        // us a nice clear time in milliseconds
        return (Sys.getTime() * 1000) / timerTicksPerSecond;
        // return System.nanoTime();
    }

    /**
     * Saves an object to a file on the filesystem.
     * 
     * @param mObject The object to save
     * @param mFilename The path and file name where to save
     */
    public static void serialize(Object mObject, String mFilename) {
        // The file where to save the image
        File theFile = new File(mFilename);

        try {
            // setup a stream to a physical file on the filesystem
            FileOutputStream outStream = new FileOutputStream(theFile);

            // attach a stream capable of writing objects to the stream that is
            // connected to the file
            ObjectOutputStream objStream = new ObjectOutputStream(outStream);

            // Write the object to the stream
            objStream.writeObject(mObject);

            // Close everything
            objStream.close();
            outStream.close();
        } catch (IOException e) {
            System.err.println("Error saving object.");
            e.printStackTrace();
        }
    }

    /**
     * Reads an object from a file in the filsystem.
     * 
     * @param mFilename The path of the file to read
     * @return The object created from the file
     */
    public static Object deserialize(String mFilename) {
        try {
            // The file to load
            File theFile = new File(mFilename);

            // Setup a stream to a physical file
            FileInputStream inStream = new FileInputStream(theFile);

            // Attach a stream capable of reading objects to the
            // stream connected to the file
            ObjectInputStream objInStream = new ObjectInputStream(inStream);

            // Load the image object from the stream
            Object object = objInStream.readObject();

            // Close everything
            objInStream.close();
            inStream.close();

            // Return the newly loaded image
            return object;
        } catch (FileNotFoundException e) {
            System.out.println("Could not find object file.");
            e.printStackTrace();
        } catch (IOException e) {
            System.err.println("Error reading object file.");
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            System.err.println("Error loading object.");
            e.printStackTrace();
        }

        // Something went wrong, so return null
        return null;
    }

    public static double round(double mNumber, int mDecimalPlaces) {
        return (int) (mNumber * (Math.pow(10, mDecimalPlaces)))
                / (double) (Math.pow(10, mDecimalPlaces));
    }
}